package com.heima.user.service.impl;

import com.heima.common.constants.user.UserRelationConstants;
import com.heima.common.exception.CustException;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.dtos.UserRelationDTO;
import com.heima.model.user.pojos.ApUser;
import com.heima.user.service.ApUserRelationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @作者 itcast
 * @创建日期 2021/9/28 16:29
 **/
@Service
@Slf4j
public class ApUserRelationServiceImpl implements ApUserRelationService {


    @Autowired
    RedisTemplate<String,String> redisTemplate;


    @Override
    public ResponseResult follow(UserRelationDTO dto) {
        //  multi ()  开启事务         exec() 执行事务       discard () 取消事务
        //     [ 命令 , 命令 ]
        // 1. 校验参数  (检查登录   检查operation 0 或 1   如果关注 不能自己关注自己   是否已经关注过 )
        ApUser loginUser = AppThreadLocalUtils.getUser();
        if (loginUser == null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        Short operation = dto.getOperation();
        if(operation.intValue()!=0 && operation.intValue()!=1){
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID,"关注状态错误");
        }
        Integer loginId = loginUser.getId();
        Integer authorUserId = dto.getAuthorApUserId();

        if (loginId.equals(authorUserId)&&operation.intValue()==0) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW,"自己不能关注自己");
        }

        ZSetOperations<String, String> zSetOper = redisTemplate.opsForZSet();
        // zscore  follow
        // 参数1： key   , 参数2: 集合中元素
        Double score = zSetOper.score(UserRelationConstants.FOLLOW_LIST + loginId, String.valueOf(authorUserId));
        if(score!=null&&operation.intValue()==0){
            CustException.cust(AppHttpCodeEnum.DATA_EXIST,"请勿重复操作");
        }
        redisTemplate.multi();
        try {
            if(operation.intValue() == 0){
                // 2. 如果是关注   zadd  follow:登录人   作者   zadd  fans:作者  登录人
                zSetOper.add(UserRelationConstants.FOLLOW_LIST+loginId,String.valueOf(authorUserId),System.currentTimeMillis());
                zSetOper.add(UserRelationConstants.FANS_LIST + authorUserId,String.valueOf(loginId),System.currentTimeMillis());
                redisTemplate.exec();
            }else {
                // 3. 如果是取关   zrem  follow:登录人  作者   zrem  fans:作者 登录人
                zSetOper.remove(UserRelationConstants.FOLLOW_LIST+loginId,String.valueOf(authorUserId));
                zSetOper.remove(UserRelationConstants.FANS_LIST + authorUserId,String.valueOf(loginId));
                redisTemplate.exec();
            }
        } catch (Exception e) {
            e.printStackTrace();
            redisTemplate.discard(); // 取消事务
            log.error("关注或取关出现异常 原因: {}",e.getMessage());
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR,"关注或取关出现异常");
        }
        // 4. 返回结果
        return ResponseResult.okResult();
    }
}